package com.hxrfid.project.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.hxrfid.common.config.WeixinConfig;
import com.hxrfid.common.constant.BasicConstants;
import com.hxrfid.common.core.domain.PageQuery;
import com.hxrfid.common.core.domain.entity.SysUser;
import com.hxrfid.common.core.page.TableDataInfo;
import com.hxrfid.common.enums.LevelEnum;
import com.hxrfid.common.enums.OrderStatusEnum;
import com.hxrfid.common.enums.OrderTypeEnum;
import com.hxrfid.common.enums.PayTypeEnum;
import com.hxrfid.common.exception.ServiceException;
import com.hxrfid.common.helper.LoginHelper;
import com.hxrfid.common.utils.IGenerateCodeService;
import com.hxrfid.common.utils.StringUtils;
import com.hxrfid.common.utils.WXPayUtils;
import com.hxrfid.common.utils.WeixinUtil;
import com.hxrfid.project.domain.BsOrder;
import com.hxrfid.project.domain.BsOrderProduct;
import com.hxrfid.project.domain.BsProduct;
import com.hxrfid.project.domain.BsUserAddress;
import com.hxrfid.project.domain.bo.BsMoneyRecordBo;
import com.hxrfid.project.domain.bo.BsOrderBo;
import com.hxrfid.project.domain.bo.BsOrderProductBo;
import com.hxrfid.project.domain.vo.*;
import com.hxrfid.project.mapper.*;
import com.hxrfid.project.service.IBsMoneyRecordService;
import com.hxrfid.project.service.IBsOrderService;
import com.hxrfid.system.mapper.SysUserMapper;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Headers;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单管理Service业务层处理
 *
 * @author hxrfid
 * @date 2025-06-12
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class BsOrderServiceImpl extends ServiceImpl<BsOrderMapper, BsOrder> implements IBsOrderService {

    private final BsOrderMapper baseMapper;
    private final BsOrderProductMapper bsOrderProductMapper;
    private final BsUserAddressMapper bsUserAddressMapper;
    private final IGenerateCodeService iGenerateCodeService;
    private final SysUserMapper sysUserMapper;
    private final BsConfigMapper configMapper;
    private final BsProductMapper bsProductMapper;
    private final IBsMoneyRecordService iBsMoneyRecordService;
    private final WeixinConfig weixinConfig;
    private final String endpoint = "https://api.mch.weixin.qq.com";
    private final WeixinUtil weixinUtil;

    /**
     * 查询订单管理
     *
     * @param id 主键ID
     * @return 订单管理
     */
    @Override
    public BsOrderVo queryById(Long id) {
        BsOrderVo bsOrderVo = baseMapper.selectVoById(id);
        // 查询订单商品
        List<BsOrderProductVo> details = bsOrderProductMapper.selectVoList(Wrappers.<BsOrderProduct>lambdaQuery().eq(BsOrderProduct::getOrderId, bsOrderVo.getId()));
        bsOrderVo.setDetails(details);
        // 查询订单地址
        BsUserAddressVo bsUserAddressVo = bsUserAddressMapper.selectVoOne(Wrappers.<BsUserAddress>lambdaQuery().eq(BsUserAddress::getId, bsOrderVo.getUserAddressId()));
        bsOrderVo.setUserAddress(bsUserAddressVo);
        return bsOrderVo;
    }

    /**
     * 根据订单号查询订单
     * @param orderNo 订单号
     * @return 订单
     */
    @Override
    public BsOrderVo queryByOrderNo(String orderNo) {
        BsOrderVo bsOrderVo = baseMapper.selectVoOne(Wrappers.<BsOrder>lambdaQuery().eq(BsOrder::getOrderNo, orderNo));
        // 查询订单商品
        List<BsOrderProductVo> details = bsOrderProductMapper.selectVoList(Wrappers.<BsOrderProduct>lambdaQuery().eq(BsOrderProduct::getOrderId, bsOrderVo.getId()));
        bsOrderVo.setDetails(details);
        // 查询订单地址
        BsUserAddressVo bsUserAddressVo = bsUserAddressMapper.selectVoOne(Wrappers.<BsUserAddress>lambdaQuery().eq(BsUserAddress::getId, bsOrderVo.getUserAddressId()));
        bsOrderVo.setUserAddress(bsUserAddressVo);
        return bsOrderVo;
    }

    /**
     * 查询订单管理列表
     *
     * @param bo        订单管理对象
     * @param pageQuery 主键ID
     * @return 订单管理列表
     */
    @Override
    public TableDataInfo<BsOrderVo> queryPageList(BsOrderBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<BsOrder> lqw = buildQueryWrapper(bo);
        Page<BsOrderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        result.getRecords().forEach(item -> {
            // 查询订单商品
            List<BsOrderProductVo> details = bsOrderProductMapper.selectVoList(Wrappers.<BsOrderProduct>lambdaQuery().eq(BsOrderProduct::getOrderId, item.getId()));
            item.setDetails(details);
            // 查询订单地址
            if (null != item.getUserAddressId()) {
                BsUserAddressVo bsUserAddressVo = bsUserAddressMapper.selectVoOne(Wrappers.<BsUserAddress>lambdaQuery().eq(BsUserAddress::getId, item.getUserAddressId()));
                item.setUserAddress(bsUserAddressVo);
            }
        });
        return TableDataInfo.build(result);
    }

    /**
     * 查询子用户列表
     * @param bo 分销员对象
     * @param pageQuery 主键ID
     * @return 子用户列表
     */
    @Override
    public TableDataInfo<MyBsOrderVo> queryPageListChild(BsOrderBo bo, PageQuery pageQuery) {
        // 查询子用户
        List<SysUser> sysUsers = sysUserMapper.selectList(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getParentId, bo.getUserId()));
        // 查询子用户订单
        List<Long> userIds = sysUsers.parallelStream().map(SysUser::getUserId).collect(Collectors.toList());
        List<String> orderStatusArr = bo.getOrderStatusArr();
        Page<MyBsOrderVo> page = baseMapper.queryPageListChild(pageQuery.build(), userIds, orderStatusArr);
        return TableDataInfo.build(page);
    }

    /**
     * 查询订单管理列表
     *
     * @param bo 订单管理对象
     * @return 订单管理列表
     */
    @Override
    public List<BsOrderVo> queryList(BsOrderBo bo) {
        LambdaQueryWrapper<BsOrder> lqw = buildQueryWrapper(bo);
        List<BsOrderVo> bsOrderVos = baseMapper.selectVoList(lqw);
        bsOrderVos.forEach(item -> {
            // 查询订单地址
            if (null != item.getUserAddressId()) {
                BsUserAddressVo bsUserAddressVo = bsUserAddressMapper.selectVoOne(Wrappers.<BsUserAddress>lambdaQuery().eq(BsUserAddress::getId, item.getUserAddressId()));
                if (null != bsUserAddressVo) {
                    item.setName(bsUserAddressVo.getName());
                    item.setPhone(bsUserAddressVo.getPhone());
                    item.setAddress(bsUserAddressVo.getAddress());
                }
            }
        });
        return bsOrderVos;
    }

    /**
     * 修改购物车
     * @param bo 订单管理对象
     * @return 修改后的订单信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public BsOrderBo editCart(BsOrderBo bo) {
        Long userId = LoginHelper.getUserId();
        // 查询用户购物车
        bo.setOrderStatus(OrderStatusEnum.ZERO.getCode());
        bo.setUserId(userId);
        BsOrderVo bsOrderVo = baseMapper.selectVoOne(Wrappers.<BsOrder>lambdaQuery().eq(BsOrder::getUserId, userId).eq(BsOrder::getOrderStatus, OrderStatusEnum.ZERO.getCode()));
        if (null != bsOrderVo) {
            bo.setId(bsOrderVo.getId());
        }
        BsOrder add = BeanUtil.toBean(bo, BsOrder.class);
        add.setProductTitles(bo.getDetails().stream().map(BsOrderProductBo::getProductTitle).collect(Collectors.joining(",")));
        baseMapper.insertOrUpdate(add);
        Long orderId = add.getId();
        // 购物车中商品
        List<BsOrderProductVo> oldList = bsOrderProductMapper.selectVoList(Wrappers.<BsOrderProduct>lambdaQuery().eq(BsOrderProduct::getOrderId, orderId));
        // 新增购物车
        if (CollectionUtil.isEmpty(oldList)) {
            bo.setId(orderId);
        } else { // 更新购物车
            List<BsOrderProductBo> addList = Lists.newArrayList();
            addList.addAll(BeanUtil.copyToList(oldList, BsOrderProductBo.class));
            List<BsOrderProductBo> newList = bo.getDetails();
            addList.addAll(BeanUtil.copyToList(newList, BsOrderProductBo.class));
            Map<Long, List<BsOrderProductBo>> mapList = addList.parallelStream().collect(Collectors.groupingBy(BsOrderProductBo::getProductId));
            List<BsOrderProductBo> insertList = Lists.newArrayList();
            mapList.forEach((productId, list) -> {
                BsOrderProductBo insert = list.get(0);
                insert.setProductNum(list.stream().mapToLong(BsOrderProductBo::getProductNum).sum());
                insertList.add(insert);
            });
            bo.setDetails(insertList);
        }
        updateOrderPruduct(bo);
        // 购物车中没有商品后删除购物车
        List<BsOrderProductBo> collect = bo.getDetails().parallelStream().filter(item -> item.getProductNum() > 0).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(collect)) {
            baseMapper.deleteById(orderId);
        }
        return bo;
    }

    /**
     * 获取用户订单金额
     *
     * @param bo 订单对象
     * @return 订单金额
     */
    @Override
    public BsOrderBo getMoney(BsOrderBo bo) {
        System.out.println("获取用户订单金额参数：" + JSONUtil.toJsonStr(bo));
        List<BsOrderProductBo> details = bo.getDetails();
        details.forEach(detail -> {
            // 商品金额=商品价格*商品数量
            BigDecimal totalPrice = NumberUtil.mul(detail.getProductPrice(), detail.getProductNum());
            detail.setTotalPrice(totalPrice);
        });
        bo.setDetails(details);
        bo.setRealPrice(getRealPrice(bo));
        return bo;
    }

    /**
     * 组装查询条件
     *
     * @param bo 订单管理对象
     * @return 查询条件
     */
    private LambdaQueryWrapper<BsOrder> buildQueryWrapper(BsOrderBo bo) {
        LambdaQueryWrapper<BsOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getOrderType()), BsOrder::getOrderType, bo.getOrderType());
        lqw.in(CollectionUtil.isNotEmpty(bo.getOrderTypes()), BsOrder::getOrderType, bo.getOrderTypes());
        lqw.eq(bo.getUserAddressId() != null, BsOrder::getUserAddressId, bo.getUserAddressId());
        lqw.eq(StringUtils.isNotBlank(bo.getPayType()), BsOrder::getPayType, bo.getPayType());
        lqw.like(StringUtils.isNotBlank(bo.getOrderNo()), BsOrder::getOrderNo, bo.getOrderNo());
        lqw.eq(bo.getOrderTime() != null, BsOrder::getOrderTime, bo.getOrderTime());
        lqw.like(StringUtils.isNotBlank(bo.getProductTitles()), BsOrder::getProductTitles, bo.getProductTitles());
        if (bo.getOrderTimeArr() != null && bo.getOrderTimeArr().length > 0) {
            lqw.ge(BsOrder::getOrderTime, bo.getOrderTimeArr()[0] + " 00:00:00");
            lqw.le(BsOrder::getOrderTime, bo.getOrderTimeArr()[1] + " 23:59:59");
        }
        lqw.eq(bo.getFreightPrice() != null, BsOrder::getFreightPrice, bo.getFreightPrice());
        lqw.eq(bo.getRealPrice() != null, BsOrder::getRealPrice, bo.getRealPrice());
        // 购物车
        if (OrderStatusEnum.ZERO.getCode().equals(bo.getOrderStatus())) {
            lqw.eq(BsOrder::getOrderStatus, bo.getOrderStatus());
        } else {
            lqw.ne(BsOrder::getOrderStatus, OrderStatusEnum.ZERO.getCode());
            lqw.eq(StringUtils.isNotBlank(bo.getOrderStatus()), BsOrder::getOrderStatus, bo.getOrderStatus());
        }
        if (CollectionUtil.isNotEmpty(bo.getOrderStatusArr())) {
            lqw.in(BsOrder::getOrderStatus, bo.getOrderStatusArr());
        }
        lqw.eq(StringUtils.isNotBlank(bo.getCommentStatus()), BsOrder::getCommentStatus, bo.getCommentStatus());
        Long userId = LoginHelper.getUserId();
        if (!LoginHelper.isAdmin(userId) && !LoginHelper.isTenantAdmin() && CollectionUtil.isEmpty(bo.getUserIds())) {
            lqw.eq(BsOrder::getUserId, userId);
        }
        lqw.in(CollectionUtil.isNotEmpty(bo.getUserIds()), BsOrder::getUserId, bo.getUserIds());
        lqw.eq(StringUtils.isNotBlank(bo.getLogisticsFirm()), BsOrder::getLogisticsFirm, bo.getLogisticsFirm());
        lqw.eq(StringUtils.isNotBlank(bo.getLogisticsNo()), BsOrder::getLogisticsNo, bo.getLogisticsNo());
        lqw.eq(bo.getBackPrice() != null, BsOrder::getBackPrice, bo.getBackPrice());
        lqw.eq(StringUtils.isNotBlank(bo.getBackLogisticsFirm()), BsOrder::getBackLogisticsFirm, bo.getBackLogisticsFirm());
        lqw.eq(StringUtils.isNotBlank(bo.getBackLogisticsNo()), BsOrder::getBackLogisticsNo, bo.getBackLogisticsNo());
        lqw.orderByDesc(BsOrder::getCreateTime);
        return lqw;
    }

    /**
     * 新增订单管理
     *
     * @param bo 订单管理对象
     * @return 是否成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean transferCart(BsOrderBo bo) {
        // 购物车id
        String nowDate = DateUtil.format(DateUtil.date(), "yyMMdd");
        bo.setOrderNo(iGenerateCodeService.generate(nowDate + BasicConstants.HYPHEN));
        bo.setOrderTime(DateUtil.date());
        validEntityBeforeSave(bo);
        BsOrder add = BeanUtil.toBean(bo, BsOrder.class);
        if (CollectionUtil.isNotEmpty(bo.getDetails())) {
            add.setProductTitles(bo.getDetails().stream().map(BsOrderProductBo::getProductTitle).collect(Collectors.joining(",")));
        }
        baseMapper.insert(add);
        // 更新订单关联商品和卡片
        bo.setId(add.getId());
        updateOrderPruduct(bo);
        // 清理购物车
        List<BsOrderProductBo> details = bo.getDetails();
        details.forEach(detail -> detail.setProductNum(NumberUtil.sub(BigDecimal.ZERO, detail.getProductNum()).longValue()));
        editCart(bo);
        return true;
    }

    /**
     * 新增订单管理
     *
     * @param bo 订单管理对象
     * @return 是否成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public BsOrder insertByBo(BsOrderBo bo) {
        String nowDate = DateUtil.format(DateUtil.date(), "yyMMdd");
        bo.setOrderNo(iGenerateCodeService.generate(nowDate + BasicConstants.HYPHEN));
        bo.setOrderTime(DateUtil.date());
        // 购买会员卡
        if (OrderTypeEnum.VIP.getCode().equals(bo.getOrderType())) {
            BsOrder add = BeanUtil.toBean(bo, BsOrder.class);
            baseMapper.insert(add);
            return add;
        } else {
            validEntityBeforeSave(bo);
            BsOrder add = BeanUtil.toBean(bo, BsOrder.class);
            baseMapper.insert(add);
            // 更新订单关联商品和卡片
            bo.setId(add.getId());
            updateOrderPruduct(bo);
            return add;
        }
    }

    /**
     * 修改订单管理
     *
     * @param bo 订单管理对象
     * @return 是否成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean updateByBo(BsOrderBo bo) {
        validEntityBeforeSave(bo);
        BsOrder update = BeanUtil.toBean(bo, BsOrder.class);
        if (OrderTypeEnum.VIP.getCode().equals(bo.getOrderType())) {
            // 更新会员级别
            SysUser sysUser = new SysUser();
            sysUser.setUserId(bo.getUserId());
            sysUser.setLevel(bo.getUserLevel());
            DateTime date = DateUtil.date();
            sysUser.setBegTime(date);
            sysUser.setEndTime(DateUtil.offset(date, DateField.YEAR, 1));
            sysUserMapper.updateById(sysUser);
        } else {
            // 更新订单关联商品和卡片
            updateOrderPruduct(bo);
        }
        if (CollectionUtil.isNotEmpty(bo.getDetails())) {
            update.setProductTitles(bo.getDetails().stream().map(BsOrderProductBo::getProductTitle).collect(Collectors.joining(",")));
        }
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 发货
     * @param bo 订单管理对象
     * @return 是否成功
     */
    @Override
    public Boolean sendByBo(BsOrderBo bo) {
        BsOrder bean = BeanUtil.toBean(bo, BsOrder.class);
        // 查询用户信息
        SysUser sysUser = sysUserMapper.selectById(bean.getUserId());
        // 把订单推送到微信订单管理
        if (StringUtils.isNotBlank(sysUser.getOpenId())) {
            weixinUtil.send(bean.getTransactionId(), bean.getOrderNo(), bean.getLogisticsNo(), bean.getLogisticsFirm(), bean.getProductTitles(), sysUser.getOpenId());
        } else {
            log.error("用户没有绑定微信:" + sysUser.getUserId());
            throw new ServiceException("用户没有绑定微信");
        }
        return baseMapper.updateById(bean) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 订单管理对象
     */
    private void validEntityBeforeSave(BsOrderBo entity) {
        String orderStatus = entity.getOrderStatus();
        if (OrderStatusEnum.TWO.getCode().equals(orderStatus)) {
            entity.setPayTime(DateUtil.date());
        }
        // 用户余额和积分变动记录
        List<BsMoneyRecordBo> boList = new ArrayList<>();
        // 订单支付后更新用户余额和积分
        if (OrderStatusEnum.TWO.getCode().equals(entity.getOrderStatus())) {
            // 更新商品库存
            updateProduct(entity);

            BigDecimal realPrice = entity.getRealPrice();
            // 查询用户是否有足够余额
            SysUser sysUser = sysUserMapper.selectVoOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUserId, entity.getUserId()));
            // 余额支付：减少用户余额
            if (PayTypeEnum.TWO.getCode().equals(entity.getPayType())) {
                if (sysUser.getMoney().compareTo(entity.getRealPrice()) < 0) {
                    throw new ServiceException("余额不足");
                } else { // 更新用户余额
                    // 减少用户余额
                    sysUser.setMoney(sysUser.getMoney().subtract(realPrice));
                    // 金额变动记录
                    boList.add(BsMoneyRecordBo.builder()
                        .title(String.format("支付订单【%s】", entity.getOrderNo()))
                        .changeNum("-" + realPrice)
                        .changeType(BasicConstants.STR_ONE)
                        .userId(entity.getUserId())
                        .payType(entity.getPayType())
                        .orderNo(entity.getOrderNo())
                        .orderTime(entity.getOrderTime())
                        .realPrice(realPrice)
                        .build());
                }
            }
            // 添加用户积分
            BsConfigVo bsConfigVo = configMapper.selectVoOne(Wrappers.lambdaQuery());
            BigDecimal addScore = realPrice.multiply(bsConfigVo.getRate());
            sysUser.setScore(NumberUtil.add(sysUser.getScore(), addScore));
            sysUserMapper.updateById(sysUser);
            // 积分变动记录
            boList.add(BsMoneyRecordBo.builder()
                .title(String.format("支付订单【%s】", entity.getOrderNo()))
                .changeNum("+" + addScore)
                .changeType(BasicConstants.STR_TWO)
                .userId(entity.getUserId())
                .payType(entity.getPayType())
                .orderNo(entity.getOrderNo())
                .orderTime(entity.getOrderTime())
                .realPrice(realPrice)
                .build());
        } else if (OrderStatusEnum.SIX.getCode().equals(entity.getOrderStatus())) { // 用户退款后更新用户余额和积分
            // 更新商品库存
            updateProduct(entity);

            BigDecimal backPrice = entity.getBackPrice();
            // 查询用户
            SysUser sysUser = sysUserMapper.selectVoOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUserId, entity.getUserId()));
            // 余额支付：退回用户余额
            if (PayTypeEnum.TWO.getCode().equals(entity.getPayType())) {
                sysUser.setMoney(sysUser.getMoney().add(backPrice));
                // 金额变动记录
                boList.add(BsMoneyRecordBo.builder()
                    .title(String.format("订单【%s】退款", entity.getOrderNo()))
                    .changeNum("+" + backPrice)
                    .changeType(BasicConstants.STR_ONE)
                    .userId(entity.getUserId())
                    .payType(entity.getPayType())
                    .orderNo(entity.getOrderNo())
                    .orderTime(entity.getOrderTime())
                    .realPrice(backPrice)
                    .build());
            }
            // 减少用户积分
            BsConfigVo bsConfigVo = configMapper.selectVoOne(Wrappers.lambdaQuery());
            BigDecimal subScore = backPrice.multiply(bsConfigVo.getRate());
            sysUser.setScore(NumberUtil.sub(sysUser.getScore(), subScore));
            sysUserMapper.updateById(sysUser);
            // 积分变动记录
            boList.add(BsMoneyRecordBo.builder()
                .title(String.format("订单【%s】退款", entity.getOrderNo()))
                .changeNum("-" + subScore)
                .changeType(BasicConstants.STR_TWO)
                .userId(entity.getUserId())
                .payType(entity.getPayType())
                .orderNo(entity.getOrderNo())
                .orderTime(entity.getOrderTime())
                .realPrice(backPrice)
                .build());
        }
        // 添加用户余额和积分变动记录
        if (CollectionUtil.isNotEmpty(boList)) {
            iBsMoneyRecordService.batchInsertByBo(boList);
        }
    }

    /**
     * 批量删除订单管理
     *
     * @param ids     主键ID的list
     * @param isValid 是否业务校验
     * @return 是否成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        List<BsOrder> list = new ArrayList<>();
        ids.forEach(id -> {
            list.add(BsOrder.builder().id(id).build());
        });
        return baseMapper.updateBatchById(list);
    }

    /**
     * 删除成员的绑定关系
     * @param userId 子用户ID
     * @return 是否成功
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public Boolean delChildOrder(Long userId) {
        List<BsOrderVo> bsOrderVos = baseMapper.selectVoList(Wrappers.<BsOrder>lambdaQuery().eq(BsOrder::getUserId, userId));
        if (CollectionUtil.isNotEmpty(bsOrderVos)) {
            List<Long> orderIds = bsOrderVos.stream().map(BsOrderVo::getId).collect(Collectors.toList());
            // 删除成员订单商品
            bsOrderProductMapper.delete(Wrappers.<BsOrderProduct>lambdaQuery().in(BsOrderProduct::getOrderId, orderIds));
        }
        // 删除订单
        baseMapper.delete(Wrappers.<BsOrder>lambdaQuery().eq(BsOrder::getUserId, userId));
        // 删除成员的绑定关系
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setParentId(null);
        sysUserMapper.updateById(sysUser);
        return true;
    }

    /**
     * 订单退款
     *
     * @param bo 退款订单
     * @return 退款结果
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean refund(BsOrderBo bo) {
        // 退款金额
        BigDecimal backPrice = bo.getBackPrice();
        // 关键参数校验
        if (backPrice == null || backPrice.compareTo(BigDecimal.ZERO) <= 0) {
            throw new ServiceException("退款金额必须大于0");
        }
        // 查询完整订单数据
        Long id = bo.getId();
        BsOrderVo order = queryById(id);
        // 状态校验
        if (!OrderStatusEnum.FIVE.getCode().equals(order.getOrderStatus())) {
            throw new ServiceException("订单不是待退款状态，不可退款");
        }
        if (OrderStatusEnum.SIX.getCode().equals(order.getOrderStatus())
            || OrderStatusEnum.SEVEN.getCode().equals(order.getOrderStatus())) {
            throw new ServiceException("订单已退款或驳回了退款，不可重复退款");
        }
        if (bo.getBackPrice().compareTo(order.getRealPrice()) > 0) {
            throw new ServiceException("退款金额不可超过订单总额");
        }
        // 微信退款
        try {
            // 执行微信退款
            executeWechatRefund(
                order, // 微信支付订单号
                iGenerateCodeService.generate("TK"),       // 生成唯一退款单号
                order.getRealPrice(),    // 订单原金额
                backPrice         // 本次退款金额
            );
        } catch (Exception e) {
            // 明确抛出业务异常
            throw new ServiceException("微信退款失败: " + e.getMessage());
        }
        return true;
    }

    /**
     * 创建微信支付
     *
     * @param bo 订单对象
     * @return 微信支付参数
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Map<String, Object> createWxPay(BsOrderBo bo) {
        // 校验订单金额
        BigDecimal realPrice = bo.getRealPrice();
        if (realPrice == null || realPrice.compareTo(BigDecimal.ZERO) <= 0) {
            throw new ServiceException("订单金额必须大于0");
        }
        // 校验openid
        SysUser sysUser = sysUserMapper.selectVoById(LoginHelper.getUserId());
        String openId = sysUser.getOpenId();
        if (StringUtils.isBlank(openId)) {
            throw new ServiceException("微信用户openid不能为空");
        }
        try {
            return executeWechatPrepay(bo, realPrice, openId);
        } catch (Exception e) {
            throw new ServiceException("微信支付下单失败: " + e.getMessage());
        }
    }

    /**
     * 计算订单金额
     *
     * @param bo 订单对象
     * @return 订单金额
     */
    private BigDecimal getRealPrice(BsOrderBo bo) {
        BigDecimal realPrice = bo.getDetails().stream().map(BsOrderProductBo::getTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (OrderTypeEnum.PRODUCT.getCode().equals(bo.getOrderType())) {
            // 查询用户会员级别
            if (null == bo.getUserId()) {
                bo.setUserId(LoginHelper.getUserId());
            }
            // 查询用户是不是新用户：用户下没有订单
            Long orderCount = baseMapper.selectCount(Wrappers.<BsOrder>lambdaQuery()
                .eq(BsOrder::getUserId, bo.getUserId())
                .ne(BsOrder::getOrderStatus, OrderStatusEnum.ZERO.getCode()));
            if (orderCount == 0) {
//                realPrice = NumberUtil.div(NumberUtil.mul(realPrice, 6.8), 10, 2);
            } else {
                DateTime date = DateUtil.date();
                SysUser sysUser = sysUserMapper.selectVoOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUserId, bo.getUserId()).le(SysUser::getBegTime, date).ge(SysUser::getEndTime, date));
                String level = LevelEnum.ZERO.getLevel();
                if (null != sysUser) {
                    level = sysUser.getLevel();
                }
                if (StringUtils.isNotBlank(level)) {
                    double discount = LevelEnum.getDiscountByLevel(level);
                    realPrice = NumberUtil.div(NumberUtil.mul(realPrice, discount), 10, 2);
                }
            }
        }
        return realPrice;
    }

    /**
     * 执行微信退款调用
     *
     * @param vo          订单
     * @param refundNo    商户退款单号
     * @param realPrice   订单原金额（元）
     * @param refundPrice 本次退款金额（元）
     */
    public void executeWechatRefund(BsOrderVo vo, String refundNo, BigDecimal realPrice, BigDecimal refundPrice) {
        // 初始化微信支付配置（从配置中心获取）
        String merchantId = weixinConfig.getMerchantId();
        String privateKey = weixinConfig.getPrivateKey();
        String merchantSerialNumber = weixinConfig.getMerchantSerialNumber();

        // 退款接口
        String url = "/v3/refund/domestic/refunds";
        // body
        CreateRequest request = new CreateRequest();
        if (StringUtils.isNotBlank(vo.getTransactionId())) {
            request.setTransactionId(vo.getTransactionId());
        } else {
            request.setOutTradeNo(vo.getOrderNo());
        }
        request.setOutRefundNo(refundNo);
        request.setReason(String.format("订单【%s】退款", vo.getOrderNo()));
        // 精确金额转换（保留两位小数）
        AmountReq amount = new AmountReq();
        amount.setTotal(realPrice.setScale(2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).longValue());
        amount.setRefund(refundPrice.setScale(2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).longValue());
        amount.setCurrency("CNY");
        request.setAmount(amount);
        String body = WXPayUtils.toJson(request);

        HttpResponse execute = HttpUtil.createPost(endpoint + url)
            .header("Authorization", WXPayUtils.buildAuthorization(merchantId, merchantSerialNumber, WXPayUtils.loadPrivateKeyFromString(privateKey), "POST", url, body))
            .header("Accept", "application/json")
            .header("Content-Type", "application/json")
            .body(WXPayUtils.toJson(request)).execute();
        JSONObject jsonObject = JSONUtil.parseObj(execute.body());
        if ("PROCESSING".equals(jsonObject.getStr("status")) || "SUCCESS".equals(jsonObject.getStr("status"))) {
            // 退款成功
            baseMapper.updateById(BsOrder.builder()
                .id(vo.getId())
                .orderStatus(OrderStatusEnum.SIX.getCode())
                .backPrice(refundPrice).build());
        } else {
            throw new RuntimeException(jsonObject.getStr("message"));
        }
    }

    /**
     * 执行微信统一下单调用
     *
     * @param order     订单对象
     * @param realPrice 订单金额（元）
     * @param openid    用户openid
     * @return 预支付响应
     */
    public Map<String, Object> executeWechatPrepay(BsOrderBo order, BigDecimal realPrice, String openid) {
        Map<String, Object> map = new HashMap<>();

        String merchantId = weixinConfig.getMerchantId();
        String privateKey = weixinConfig.getPrivateKey();
        String merchantSerialNumber = weixinConfig.getMerchantSerialNumber();
        String appId = weixinConfig.getAppId();
        /** body参数 */
        PrepayRequest request = new PrepayRequest();
        request.setAppid(appId);
        request.setMchid(merchantId);
        request.setDescription("订单支付 - " + order.getOrderNo());
        request.setOutTradeNo(order.getOrderNo());
        request.setNotifyUrl("https://www.huayunzhi2025.com/api/open/api/wxPayNotify"); // 需要配置为实际的回调地址
        // 设置支付者信息（需要前端传入openid）
        Payer payer = new Payer();
        payer.setOpenid(openid);
        request.setPayer(payer);
        // 设置金额信息
        Amount amount = new Amount();
        amount.setTotal(realPrice.setScale(2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).intValue());
        amount.setCurrency("CNY");
        request.setAmount(amount);
        String body = WXPayUtils.toJson(request);

        // 请求接口
        String url = "/v3/pay/transactions/jsapi";
        try {
            HttpResponse execute = HttpUtil.createPost(endpoint + url)
                .header("Authorization", WXPayUtils.buildAuthorization(merchantId, merchantSerialNumber, WXPayUtils.loadPrivateKeyFromString(privateKey), "POST", url, body))
                .header("Accept", "application/json")
                .body(body).execute();
            map.put("appId", appId);
            long timeStamp = Instant.now().getEpochSecond();
            map.put("timeStamp", timeStamp);
            String nonceStr = WXPayUtils.createNonce(32);
            map.put("nonceStr", nonceStr);
            JSONObject jsonObject = JSONUtil.parseObj(execute.body());
            String prepayId = "prepay_id=" + jsonObject.getStr("prepay_id");
            map.put("package", prepayId);
            map.put("signType", "RSA");
            String message = String.format("%s\n%s\n%s\n%s\n", appId, timeStamp, nonceStr, prepayId);
            map.put("paySign", WXPayUtils.sign(message, "SHA256withRSA", WXPayUtils.loadPrivateKeyFromString(privateKey)));
            return map;
        } catch (Exception e) {
            throw new RuntimeException("微信下单失败：" + e.getMessage());
        }
    }

    /**
     * 处理微信支付回调通知
     *
     * @param request 请求对象
     * @return 回调响应
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public String handleWxPayNotify(HttpServletRequest request) {
        // 从request获取Headers
        Enumeration<String> headerNames = request.getHeaderNames();
        Headers.Builder headersBuilder = new Headers.Builder();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            headersBuilder.add(headerName, headerValue);
        }
        Headers headers = headersBuilder.build();
        System.out.println("收到微信支付回调headers: " + headers);
        // 从request获取body
        BufferedReader reader;
        try {
            reader = request.getReader();
        } catch (IOException e) {
            throw new RuntimeException("读取应答body出错");
        }
        StringBuilder sb = new StringBuilder();
        String line;
        while (true) {
            try {
                if ((line = reader.readLine()) == null) break;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            sb.append(line);
        }
        String body = sb.toString();
        System.out.println("收到微信支付回调body: " + body);
        WXPayUtils.validateResponse(weixinConfig.getWechatpayPublicKeyId(), WXPayUtils.loadPublicKeyFromString(weixinConfig.getPublicKey()), headers, body);
        // 解析回调数据
        JSONObject jsonObject = JSONUtil.parseObj(body);
        String resourceType = jsonObject.getStr("resource_type");
        if ("encrypt-resource".equals(resourceType)) {
            // 解密资源数据
            JSONObject resource = jsonObject.getJSONObject("resource");
            String ciphertext = resource.getStr("ciphertext");
            String nonceStr = resource.getStr("nonce");
            String associatedData = resource.getStr("associated_data");
            // 解密通知数据
            String decryptedData = WXPayUtils.decryptNotification(ciphertext, nonceStr, associatedData, weixinConfig.getApiV3Key());
            JSONObject transactionData = JSONUtil.parseObj(decryptedData);
            // 打印订单号和微信支付单号
            String outTradeNo = transactionData.getStr("out_trade_no");
            String transactionId = transactionData.getStr("transaction_id");
            // 更新订单支付单号
            BsOrder order = new BsOrder();
            order.setTransactionId(transactionId);
            order.setUpdateBy("微信支付回调");
            baseMapper.update(order, new QueryWrapper<BsOrder>().eq("order_no", outTradeNo));
            log.info("支付成功，商户订单号: {}，微信支付单号: {}", outTradeNo, transactionId);
            return "{\"code\":\"SUCCESS\",\"message\":\"成功\"}";
        } else {
            throw new ServiceException("支付失败");
        }
    }

    /**
     * 检测库存
     * @param details 订单商品
     * @return 检测结果
     */
    @Override
    public String checkInventory(List<BsOrderProductBo> details) {
        Assert.notEmpty(details, "商品不能为空！");
        StringBuilder sb = new StringBuilder();
        for (BsOrderProductBo detail : details) {
            BsProduct product = bsProductMapper.selectById(detail.getProductId());
            if (product.getInventory() < detail.getProductNum()) {
                sb.append("\n").append(String.format("【%s】库存不足", product.getTitle()));
            }
        }
        return StringUtils.isNotBlank(sb) ? sb.substring(1) : "";
    }

    /**
     * 更新订单关联商品
     */
    private void updateOrderPruduct(BsOrderBo order) {
        List<BsOrderProductBo> details = order.getDetails();
        if (CollectionUtil.isNotEmpty(details)) {
            details.forEach(detail -> detail.setOrderId(order.getId()));
            // 删除订单关联商品
            bsOrderProductMapper.delete(new QueryWrapper<BsOrderProduct>().eq("order_id", order.getId()));
            // 新增订单关联商品
            List<BsOrderProductBo> collect = details.parallelStream().filter(item -> item.getProductNum() > 0).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(collect)) {
                bsOrderProductMapper.insertOrUpdateBatch(BeanUtil.copyToList(collect, BsOrderProduct.class));
            }
        }
    }

    /**
     * 更新商品库存和销量
     * @param entity 订单
     */
    private void updateProduct(BsOrderBo entity) {
        String orderType = entity.getOrderType();
        if (OrderTypeEnum.PRODUCT.getCode().equals(orderType)) {
            List<BsProduct> productList = new ArrayList<>();

            List<BsOrderProductBo> details = entity.getDetails();
            if (CollectionUtil.isEmpty(details)) {
                List<BsOrderProductVo> bsOrderProductVos = bsOrderProductMapper.selectVoList(Wrappers.<BsOrderProduct>lambdaQuery().eq(BsOrderProduct::getOrderId, entity.getId()));
                details = BeanUtil.copyToList(bsOrderProductVos, BsOrderProductBo.class);
            }
            details.forEach(detail -> {
                BsProduct product = new BsProduct();
                product.setId(detail.getProductId());
                if (OrderStatusEnum.SIX.getCode().equals(entity.getOrderStatus())) {
                    product.setInventory(detail.getProductNum());
                    product.setSaleNum(BasicConstants.ZERO - detail.getProductNum());
                } else if (OrderStatusEnum.TWO.getCode().equals(entity.getOrderStatus())) {
                    product.setInventory(BasicConstants.ZERO - detail.getProductNum());
                    product.setSaleNum(detail.getProductNum());
                }

                productList.add(product);
            });
            bsProductMapper.updateBatchById(productList);
        }
    }

}
